// $codepro.audit.disable assignmentInCondition, booleanMethodNamingConvention
/*
 * AccountsController.java
 */

package edu.gatech.oad.user;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import edu.gatech.oad.persistence.PersistentObject;

public class AccountsController extends PersistentObject {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private final Map<String, Patient> patients;
	
	private final Map<String, Doctor> doctors;
	
	private final Map<String, Nurse> nurses;
	
	private final Map<String, Receptionist> receptionists;
	
	private final Map<String, SystemAdministrator> administrators;
	
	private static AccountsController SHARED_CONTROLLER; // $codepro.audit.disable initializeStaticFields
	
	public AccountsController() { // $codepro.audit.disable com.instantiations.assist.eclipse.analysis.audit.rule.effectivejava.enforceTheSingletonPropertyWithAPrivateConstructor
		patients = new HashMap<String, Patient>();
		doctors = new HashMap<String, Doctor>();
		nurses = new HashMap<String, Nurse>();
		receptionists = new HashMap<String, Receptionist>();
		administrators = new HashMap<String, SystemAdministrator>();
	}
	
	public static void setSharedController(AccountsController controller) {
		SHARED_CONTROLLER = controller;
	}
	
	public static AccountsController sharedController() {
		if (SHARED_CONTROLLER == null) {
			SHARED_CONTROLLER = new AccountsController();
		}
		return SHARED_CONTROLLER;
	}
	
	public User getUserForUsername(String username) {
		User user = null;
		if ((user = getPatientForUsername(username)) != null) {
			return user;
		}
		else if ((user = getDoctorForUsername(username)) != null) {
			return user;
		}
		else if ((user = getNurseForUsername(username)) != null) {
			return user;
		}
		else if ((user = getReceptionistForUsername(username)) != null) {
			return user;
		}
		else if ((user = getSystemAdministratorForUsername(username)) != null) {
			return user;
		}
		return user;
	}
	
	public Patient getPatientForUsername(String username) {
		return this.patients.get(username);
	}
	
	public Doctor getDoctorForUsername(String username) {
		return this.doctors.get(username);
	}
	
	public Nurse getNurseForUsername(String username) {
		return this.nurses.get(username);
	}
	
	public Receptionist getReceptionistForUsername(String username) {
		return this.receptionists.get(username);
	}
	
	public SystemAdministrator getSystemAdministratorForUsername(String username) {
		return this.administrators.get(username);
	}
	
	public Set<User> getUsers() {
		final Set<User> users = new HashSet<User>(patients.values());
		users.addAll(doctors.values());
		users.addAll(nurses.values());
		users.addAll(receptionists.values());
		users.addAll(administrators.values());
		return users;
	}
	
	public Set<Patient> getPatients() {
		return new HashSet<Patient>(patients.values());
	}
	
	public Set<Doctor> getDoctors() {
		return new HashSet<Doctor>(doctors.values());
	}
	
	public Set<Nurse> getNurses() {
		return new HashSet<Nurse>(nurses.values());
	}
	
	public Set<Receptionist> getReceptionists() {
		return new HashSet<Receptionist>(receptionists.values());
	}
	
	public Set<SystemAdministrator> getSystemAdministrators() {
		return new HashSet<SystemAdministrator>(administrators.values());
	}
		
	public Patient addPatientForUsername(String username) {
		//check for a preexisting user with the given username; if there is one, return null
		if (getUserForUsername(username) != null) {
			return null;
		}
		
		final Patient patient = new Patient(username);
		patients.put(username, patient);
		return patient;
	}
	
	public Doctor addDoctorForUsername(String username) {
		//check for a preexisting user with the given username; if there is one, return null
		if (getUserForUsername(username) != null) {
			return null;
		}
		
		final Doctor doctor = new Doctor(username);
		doctors.put(username, doctor);
		return doctor;
	}
	
	public Nurse addNurseForUsername(String username) {
		//check to make sure that there isn't a user with the given username; if there is one, return null
		if (getUserForUsername(username) != null) {
			return null;
		}
		
		final Nurse nurse = new Nurse(username);
		nurses.put(username, nurse);
		return nurse;
	}
	
	public Receptionist addReceptionistForUsername(String username) {
		//check to make sure that there isn't a user already registered with the username; if there is, return null
		if (getUserForUsername(username) != null) {
			return null;
		}
		
		final Receptionist receptionist = new Receptionist(username);
		receptionists.put(username, receptionist);
		return receptionist;
	}
	
	public SystemAdministrator addSystemAdministratorForUsername(String username) {
		//We need to do some duplicate checking, so that a user can't be overwritten; we'll return null if there is already a user for the given username.
		if (getUserForUsername(username) != null) {
			return null;
		}
		
		final SystemAdministrator admin = new SystemAdministrator(username);
		administrators.put(username, admin);
		return admin;
	}
	
	public boolean removeUserForUsername(String username) {
		return removePatientForUsername(username) || removeDoctorForUsername(username) || 
			removeNurseForUsername(username) || removeReceptionistForUsername(username) ||
			removeSystemAdministratorForUsername(username);
	}
	
	public boolean removePatientForUsername(String username) {
		final Patient patient = getPatientForUsername(username);
		if (patient != null) {
			this.patients.remove(username);
			return true;
		}
		return false;
	}
	
	public boolean removeDoctorForUsername(String username) {
		final Doctor doctor = getDoctorForUsername(username);
		if (doctor != null) {
			this.doctors.remove(username);
			return true;
		}
		return false;
	}
	
	public boolean removeNurseForUsername(String username) {
		final Nurse nurse = getNurseForUsername(username);
		if (nurse != null) {
			this.nurses.remove(username);
			return true;
		}
		return false;
	}
	
	public boolean removeReceptionistForUsername(String username) {
		final Receptionist receptionist = getReceptionistForUsername(username);
		if (receptionist != null) {
			this.receptionists.remove(username);
			return true;
		}
		return false;
	}
	
	public boolean removeSystemAdministratorForUsername(String username) {
		final SystemAdministrator admin = getSystemAdministratorForUsername(username);
		if (admin != null) {
			this.administrators.remove(username);
			return true;
		}
		return false;
	}
	
	public String toString() {
		return "AccountsController: " + getUsers().toString();
	}
}
